package services

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/goravel/framework/facades"
	"github.com/goravel/framework/support/path"
	"github.com/mitchellh/mapstructure"
	"github.com/spf13/cast"
	"goravel/app/models"
	"gorm.io/gorm"
	"os"
	"regexp"
	"strings"
	"time"
)

type KillLogService struct {
	ParseFile *os.File
	KillRule  *KillRule
	Path      string
	CommonService
}

func (p *KillLogService) NewKillLogService(foldPath string, fileList []string) *KillLogService {
	return &KillLogService{
		ParseFile: p.MergeFile(foldPath, fileList),
		//ParseFile: p.LoadMergeFile(),
	}
}
func (p *KillLogService) LoadMergeFile() *os.File {
	file, err := os.Open(path.Public("storage/sftp/merge/kills_merge.log"))
	if err != nil {
		panic(err)
	}
	return file
}
func (p *KillLogService) MergeFile(foldPath string, pathList []string) *os.File {
	err := os.MkdirAll(path.Public(foldPath+"merge"), os.ModePerm)
	if err != nil {
		panic(err)
	}
	//看一下里面是否有文件，有就删除，删除之后再创建新文件
	_, err = os.Stat(path.Public(foldPath + "merge/kills_merge.log"))
	if err == nil {
		err = os.Remove(path.Public(foldPath + "merge/kills_merge.log"))
		if err != nil {
			panic(err)
		}
	}
	file, err := os.Create(path.Public(foldPath + "merge/kills_merge.log"))

	writer := bufio.NewWriter(file)
	for i, s := range pathList {
		file_item, _ := os.Open(path.Public(foldPath + s))
		defer file.Close()
		scanner := bufio.NewScanner(file_item)
		for scanner.Scan() {
			writer.WriteString(scanner.Text() + "\n")
		}
		if i == len(pathList)-1 {
			writer.Flush()
		}
	}
	retfile, err := os.Open(path.Public(foldPath + "merge/kills_merge.log"))
	if err != nil {
		panic(err)
	}
	return retfile
}

type Location struct {
	X float64 `json:"X"`
	Y float64 `json:"Y"`
	Z float64 `json:"Z"`
}

type Player struct {
	ServerLocation Location `json:"ServerLocation"`
	ClientLocation Location `json:"ClientLocation"`
	IsInGameEvent  bool     `json:"IsInGameEvent"`
	ProfileName    string   `json:"ProfileName"`
	UserId         string   `json:"UserId"`
	HasImmortality bool     `json:"HasImmortality"`
}

type KillEvent struct {
	Killer    Player `json:"Killer"`
	Victim    Player `json:"Victim"`
	Weapon    string `json:"Weapon"`
	TimeOfDay string `json:"TimeOfDay"`
}

// 逐行读取
func (p *KillLogService) ReadKillLockLine(id uint, rids []uint) {
	fileScanner := bufio.NewScanner(p.ParseFile)
	fileScanner.Split(bufio.ScanLines)

	//	每隔10s输出一次日志，fileScanner.Scan()执行完毕后，退出,定义单通道channel
	var flagChan = make(chan bool)
	//定义定时器
	ticker := time.NewTicker(time.Second * 10)
	var user_id uint
	facades.Orm().Query().Model(&models.Configuration{}).Where("id=?", id).Pluck("user_id", &user_id)
	//开启协程
	go func() {
		for {
			select {
			case <-ticker.C:
				p.CommonService.Notice(user_id, `击杀日志解析中|(2:10)`)
			case <-flagChan:
				//fmt.Println("退出")
				ticker.Stop()
				return
			}
		}
	}()

	for fileScanner.Scan() {
		//或者包含了某些字符 Game version
		if fileScanner.Text() == "" || strings.Contains(fileScanner.Text(), "Game version") || strings.Contains(fileScanner.Text(), "Died:") || strings.Contains(fileScanner.Text(), "Comitted suicide.") {
			continue
		}
		txt := fileScanner.Text()
		actionTime, objStr := p.ExtractTime(txt)
		if objStr != nil {
			killevent := KillEvent{}
			mapstructure.Decode(objStr, &killevent)
			killLog := models.KillLog{
				ActionTime:      actionTime,
				KillerName:      killevent.Killer.ProfileName,
				KillerSteamid:   killevent.Killer.UserId,
				KillType:        "",
				VictimName:      killevent.Victim.ProfileName,
				VictimSteamid:   killevent.Victim.UserId,
				WeaponType:      "",
				Weapon:          killevent.Weapon,
				Distance:        "",
				Activity:        killevent.Killer.IsInGameEvent,
				VictimArea:      p.getLockArea(killevent.Killer.ServerLocation.X, killevent.Killer.ServerLocation.Y),
				KillerArea:      p.getLockArea(killevent.Victim.ServerLocation.X, killevent.Victim.ServerLocation.Y),
				VictimPosition:  fmt.Sprintf("x:%f,y%f", killevent.Victim.ServerLocation.X, killevent.Victim.ServerLocation.Y),
				KillerPosition:  fmt.Sprintf("x:%f,y%f", killevent.Killer.ServerLocation.X, killevent.Killer.ServerLocation.Y),
				OriginalText:    txt,
				ConfigurationID: cast.ToInt(id),
			}
			err := facades.Orm().Query().
				Where("original_text = ?", txt).
				FirstOrFail(&killLog)
			if errors.Is(err, gorm.ErrRecordNotFound) {
				facades.Orm().Query().Create(&killLog)
			}

		}
	}
	//fileScanner是否扫描完毕
	if !fileScanner.Scan() {
		flagChan <- true
		p.CommonService.Notice(user_id, `击杀日志解析完成|(2:10)`)

	}

	facades.Orm().Query().Model(&models.DownloadRecord{}).Where("id=?", rids).Update("is_need_download_and_parse", 0)
	p.ParseFile.Close()
}

func (p *KillLogService) ExtractTime(txt string) (string, map[string]interface{}) {
	//	2023.11.26-15.46.17: {"Killer":{"ServerLocation":{"X": 325985.65625,"Y": -370405.1875,"Z": 12750.7392578125},"ClientLocation":{"X": 325985.65625,"Y": -370405.1875,"Z": 12750.7392578125},"IsInGameEvent": false,"ProfileName": "自强","UserId": "76561199520250880","HasImmortality": false},"Victim":{"ServerLocation":{"X": 328598.8125,"Y": -370545.34375,"Z": 12733.5498046875},"ClientLocation":{"X": 328606.9375,"Y": -370555.59375,"Z": 12703.330078125},"IsInGameEvent": false,"ProfileName": "madadiao5839","UserId": "76561199128128806"},"Weapon": "Weapon_VSS_VZ_C [Projectile]","TimeOfDay": "19:36:09"}
	//使用正则，将前面的日期提取出来，新的字符串删除该日期
	timeStr := txt[:19]
	//正则匹配时间
	reg := regexp.MustCompile(`\d{4}\.\d{2}\.\d{2}-\d{2}\.\d{2}\.\d{2}:\s+(.*)`)
	strslice := reg.FindStringSubmatch(txt)
	if len(strslice) == 0 {
		return "", nil
	}
	var jsonDataMap map[string]interface{}
	err := json.Unmarshal([]byte(strslice[1]), &jsonDataMap)
	if err != nil {
		fmt.Println("解析JSON失败:", err)
		return "", nil
	}

	return timeStr, jsonDataMap
}

// 开锁区域三：根据x和y的值判断
func (p *KillLogService) getLockArea(x float64, y float64) string {
	//1、将x和y转换为float64
	xfloat64 := cast.ToFloat64(x)
	yfloat64 := cast.ToFloat64(y)
	if 599996.750 > xfloat64 && xfloat64 > 904795.125 && -295198.375 > yfloat64 && yfloat64 > -599996.750 {
		return "A0"
	}
	if -295198.375 > xfloat64 && xfloat64 > -599996.750 && -295198.375 > yfloat64 && yfloat64 > -599996.750 {
		return "A1"
	}
	if 9600.000 > xfloat64 && xfloat64 > -295198.375 && -295198.375 > yfloat64 && yfloat64 > -599996.750 {
		return "A2"
	}
	if 314398.375 > xfloat64 && xfloat64 > 9600.000 && -295198.375 > yfloat64 && yfloat64 > -599996.750 {
		return "A3"
	}
	if 619196.750 > xfloat64 && xfloat64 > 314398.375 && -295198.375 > yfloat64 && yfloat64 > -599996.750 {
		return "A4"
	}
	if -599996.750 > xfloat64 && xfloat64 > -904795.125 && 9600.000 > yfloat64 && yfloat64 > -295198.375 {
		return "B1"
	}
	if -295198.375 > xfloat64 && xfloat64 > -599996.750 && 9600.000 > yfloat64 && yfloat64 > -295198.375 {
		return "B1"
	}
	if 9600.000 > xfloat64 && xfloat64 > -295198.375 && 9600.000 > yfloat64 && yfloat64 > -295198.375 {
		return "B2"
	}
	if 314398.375 > xfloat64 && xfloat64 > 9600.000 && 9600.000 > yfloat64 && yfloat64 > -295198.375 {
		return "B3"
	}
	if 619196.750 > xfloat64 && xfloat64 > 314398.375 && 9600.000 > yfloat64 && yfloat64 > -295198.375 {
		return "B4"
	}
	if -599996.750 > xfloat64 && xfloat64 > -904795.125 && 314398.375 > yfloat64 && yfloat64 > 9600.000 {
		return "C0"
	}
	if -295198.375 > xfloat64 && xfloat64 > -599996.750 && 314398.375 > yfloat64 && yfloat64 > 9600.000 {
		return "C1"
	}
	if 9600.000 > xfloat64 && xfloat64 > -295198.375 && 314398.375 > yfloat64 && yfloat64 > 9600.000 {
		return "C2"
	}
	if 314398.375 > xfloat64 && xfloat64 > 9600.000 && 314398.375 > yfloat64 && yfloat64 > 9600.000 {
		return "C3"
	}
	if 619196.750 > xfloat64 && xfloat64 > 314398.375 && 314398.375 > yfloat64 && yfloat64 > 9600.000 {
		return "C4"
	}

	if -599996.750 > xfloat64 && xfloat64 > -904795.125 && 619196.750 > yfloat64 && yfloat64 > 314398.375 {
		return "D0"
	}
	if -295198.375 > xfloat64 && xfloat64 > -599996.750 && 619196.750 > yfloat64 && yfloat64 > 314398.375 {
		return "D1"
	}
	if 9600.000 > xfloat64 && xfloat64 > -295198.375 && 619196.750 > yfloat64 && yfloat64 > 314398.375 {
		return "D2"
	}
	if 314398.375 > xfloat64 && xfloat64 > 9600.000 && 619196.750 > yfloat64 && yfloat64 > 314398.375 {
		return "D3"
	}
	if 619196.750 > xfloat64 && xfloat64 > 314398.375 && 619196.750 > yfloat64 && yfloat64 > 314398.375 {
		return "D4"
	}

	if -599996.750 > xfloat64 && xfloat64 > -904795.125 && -599996.750 > yfloat64 && yfloat64 > -904795.125 {
		return "Z0"
	}
	if -295198.375 > xfloat64 && xfloat64 > -599996.750 && -599996.750 > yfloat64 && yfloat64 > -904795.125 {
		return "Z1"
	}
	if 9600.000 > xfloat64 && xfloat64 > -295198.375 && -599996.750 > yfloat64 && yfloat64 > -904795.125 {
		return "Z2"
	}
	if 314398.375 > xfloat64 && xfloat64 > 9600.000 && -599996.750 > yfloat64 && yfloat64 > -904795.125 {
		return "Z3"
	}
	if 619196.750 > xfloat64 && xfloat64 > 314398.375 && -599996.750 > yfloat64 && yfloat64 > -904795.125 {
		return "Z4"
	}
	//2、判断x和y的范围
	//3、返回对应的区域
	return ""
}
